home *** CD-ROM | disk | FTP | other *** search
Text File | 1990-06-24 | 35.7 KB | 840 lines | [TEXT/CCL ] |
- ; (c) Copyright 1990 by University of Massachusetts. All rights reserved.
- ; This software was conceived, designed, and written by Dan Suthers
- ; while supported by the National Science Foundation under grant number
- ; MDR 8751362, and by a fellowship from Apple Computer, Inc., Cupertino,
- ; CA. Partial support was also received from the Office of Naval Research
- ; under a University Research Initiative Grant, contract N00014-86-K-0764.
- ; Mr. Suthers created this software under his own initiative while in an
- ; academic relationship with the University of Massachusetts. The above
- ; copyright notice was a condition placed by University lawyers on approval
- ; of distribution of this software by Apple Computer, and is not meant to
- ; imply that this software was created in an employment or "work for hire"
- ; relationship between the University and Mr. Suthers.
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; File: HNET-BROWSER.LISP
- ; Author: Dan Suthers
- ; Created: 27-May-88 23:34:08
- ; Modified: 22-Jun-90 02:30:07 (Dan Suthers)
- ; Language: LISP
- ; Package: HNET
- ;
- ; Description: Allows interactive examination of the HNET.
- ;
- ; (c) Copyright 1988, by Daniel D. Suthers
- ; Department of Computer and Information Science
- ; University of Massachusetts
- ; Amherst, Massachusetts 01003
- ;
- ; This software was conceived, designed, and written by Dan Suthers
- ; while supported by the National Science Foundation under grant number
- ; MDR 8751362, and by a fellowship from Apple Computer, Inc., Cupertino,
- ; CA. Partial support was also received from the Office of Naval Research
- ; under a University Research Initiative Grant, contract N00014-86-K-0764.
- ; I wish to acknowledge the generous support of Beverly Woolf, who obtained
- ; the above grants and encouraged me to pursue my own research interests in
- ; her lab. This work would not have been possible without the resources and
- ; stimulating environment of the Computer and Information Science department.
- ;
- ; Permission to use, modify, and distribute this software is granted subject
- ; to the following restrictions and understandings:
- ; 1. The file header, including this notice, shall be retained, and may be
- ; extended to include documentation of modifications to the software.
- ; 2. This material is for nonprofit educational and research purposes only.
- ; Users are requested, but not required, to inform Mr. Suthers of any
- ; noteworthy uses of this software.
- ; 3. Mr. Suthers and the University of Massachusetts make no warrantee or
- ; representation that the operation of this software will be error free,
- ; and are under no obligation to provide any services.
- ; 4. Any user of such software agrees to indemnify and hold harmless Mr.
- ; Suthers and the University of Massachusetts from all claims arising
- ; out of the use or misuse of this software, or arising out of any
- ; accident, injury, or damage whatsoever, and from all costs, counsel
- ; fees, and liabilities incurred in or about any such claim, action, or
- ; proceeding brought thereon.
- ; 5. All materials and reports developed as a consequence of the use of
- ; this software shall duly acknowledge such use, in accordance with
- ; the usual standards of acknowledging credit in academic research.
- ;
- ; Status: Usable but could use lots of improvement as an interface.
- ; I recommend using the Grapher and writing network editing
- ; mouse methods instead of this primitive interface.
- ;
- ; Tested: Macintosh II Coral/Allegro 27-Jun-88 Dan Suthers
- ;
- ; Changes:
- ; 23-Jul-88 Don't show superordinate* in browser; takes too long.
- ; Grapher no longer creates graph-nodes for terms not being graphed,
- ; and finds the roots via new hnet-roots.
- ; 25-Sep-88 New Grapher mouse-methods. Dive in to sub-views and come back,
- ; etc. Many other grapher-related changes.
- ; 04-Nov-88 Removed sort of HNET names (already sorted by :sort-instances);
- ; Backup to Parent View mouse method restores gv to gw if there is no
- ; parent view (bug introduced by 01-Nov change to MacGrapher).
- ; 15-Dec-88 Backup All the Way to Original View added to mouse methods.
- ; 27-Dec-88 Eliminated graph-node-parents.
- ; 11-Jan-88 Changed to accept any object as terms, not just symbols.
- ; 17-Apr-89 Changed a path name.
- ; 30-Jan-90 Updated for version 1.3.1: window-draw-contents -> view-...;
- ; default-button now in button items.
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- (in-package :HNET)
-
- (export '(
- browse-hnet
- graph-hnet
- hnet->graph-view-with-parameters
- ))
-
- (require :MISC )
- (require :DIALOGUE)
- (require :SM )
- (require :SMEDIT )
- (require :HNET )
- (require :GRAPHER )
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- (eval-when (compile eval)
-
- (defmacro OBJECT->STRING (object)
- `(typecase ,object
- (symbol (symbol-name ,object))
- (string ,object)
- (otherwise (format nil "~S" ,object))))
-
- (defmacro NO-HNET-SELECTED-HANDLER ()
- ;; Disable term menu and buttons.
- '(progn
- (ccl:ask ; term-menu
- (second (ccl:ask ccl:my-dialog (ccl:dialog-items)))
- (ccl:set-table-sequence nil))
- (ccl:ask ; add-term
- (fifth (ccl:ask ccl:my-dialog (ccl:dialog-items)))
- (ccl:dialog-item-disable))
- (ccl:ask ; delete-term
- (sixth (ccl:ask ccl:my-dialog (ccl:dialog-items)))
- (ccl:dialog-item-disable))
- (ccl:ask ; add-super
- (seventh (ccl:ask ccl:my-dialog (ccl:dialog-items)))
- (ccl:dialog-item-disable))
- (ccl:ask ; delete-super
- (eighth (ccl:ask ccl:my-dialog (ccl:dialog-items)))
- (ccl:dialog-item-disable))
- (ccl:ask ; show-supers
- (ninth (ccl:ask ccl:my-dialog (ccl:dialog-items)))
- (ccl:dialog-item-disable))
- (ccl:ask ; show-subs
- (tenth (ccl:ask ccl:my-dialog (ccl:dialog-items)))
- (ccl:dialog-item-disable))))
-
- (defmacro NO-TERM-SELECTED-HANDLER ()
- '(progn
- ;; Ensure nothing is selected (useful after adding or deleting terms).
- (ccl:ask ; term-menu
- (second (ccl:ask ccl:my-dialog (ccl:dialog-items)))
- (if (ccl:selected-cells)
- (ccl:cell-deselect (car (ccl:selected-cells)))))
- ;; Disable stuff.
- (ccl:ask ; delete-term
- (sixth (ccl:ask ccl:my-dialog (ccl:dialog-items)))
- (ccl:dialog-item-disable))
- (ccl:ask ; add-super
- (seventh (ccl:ask ccl:my-dialog (ccl:dialog-items)))
- (ccl:dialog-item-disable))
- (ccl:ask ; delete-super
- (eighth (ccl:ask ccl:my-dialog (ccl:dialog-items)))
- (ccl:dialog-item-disable))
- (ccl:ask ; term-relation
- (tenth (ccl:ask ccl:my-dialog (ccl:dialog-items)))
- (ccl:dialog-item-disable))))
-
- (defmacro WITH-GIVEN-OBJECT (&rest body)
- ;; Binds OBJECT to the object correponding to the typed string,
- ;; and executes <body>, unless an error is encountered.
- `(let ((term-string
- (ccl:ask ; entry-window
- (third (ccl:ask ccl:my-dialog (ccl:dialog-items)))
- (ccl:dialog-item-text)))
- (object nil))
- (setf object (read-from-string term-string nil '$eof$))
- (cond
- ((eq object '$eof$)
- (ccl:ed-beep)
- (ccl:ask ; display-window
- (fourth (ccl:ask ccl:my-dialog (ccl:dialog-items)))
- (ccl:set-dialog-item-text "Error on read of your object. Please type a~
- ~%readable object in the entry window above.")))
- (T ,@body))))
-
- (defmacro WITH-HNET (&rest body)
- ;; binds HNET to an existing term chosen from the menu.
- `(let ((hnet
- (ccl:ask ; hnet-menu
- (first (ccl:ask ccl:my-dialog (ccl:dialog-items)))
- (if (ccl:selected-cells)
- ;; Got an HNET
- (ccl:cell-contents (car (ccl:selected-cells)))
- ;; No HNET: disable related buttons.
- (progn
- (ccl:ed-beep)
- (no-hnet-selected-handler))))))
- (when hnet ,@body)))
-
- (defmacro WITH-TERM (&rest body)
- ;; Binds TERM to an existing term chosen from the menu.
- `(let ((term
- (if
- ;; If there is an hnet selected ...
- (ccl:ask ; hnet-menu
- (first (ccl:ask ccl:my-dialog (ccl:dialog-items)))
- (ccl:selected-cells))
- ;; Then it is OK to see if a term is selected.
- (ccl:ask ; term-menu
- (second (ccl:ask ccl:my-dialog (ccl:dialog-items)))
- (if (ccl:selected-cells)
- ;; Got a TERM
- (ccl:cell-contents (car (ccl:selected-cells)))
- ;; Otherwise disable TERM buttons
- (progn
- (ccl:ed-beep)
- (no-term-selected-handler))))
- ;; Otherwise disable HNET buttons
- (progn
- (ccl:ed-beep)
- (no-hnet-selected-handler)))))
- (when term ,@body)))
-
- ) ; end of eval-when
-
- (defun OBJECT-LESSP (t1 t2)
- (declare (optimize speed))
- (string< (object->string t1) (object->string t2)))
-
- (defun BROWSE-HNET ()
- "browse-hnet [Function]
- Creates and returns an HNET browser object."
- (let*
- (
- ;;----------------
- ;; Display Windows
-
- ;; Window in which user types names of terms.
- (entry-window
- (ccl:oneof
- ccl:*editable-text-dialog-item*
- :dialog-item-size (ccl:make-point 275 16)
- :dialog-item-position (ccl:make-point 137 88)
- :dialog-item-font '("monaco" 12)
- :dialog-item-text ""
- :allow-returns nil))
-
- ;; Window where hnet and term descriptions are displayed.
- (display-window
- (ccl:oneof
- ccl:*editable-text-dialog-item*
- :dialog-item-size (ccl:make-point 580 180)
- :dialog-item-position (ccl:make-point 10 120)
- :dialog-item-font '("monaco" 12)
- :dialog-item-text
- "
- Choose an HNET first, using the menu on the left. When you do, all the
- terms in the chosen HNET will be listed in the right menu. You may add
- terms or list undefined terms using the enabled buttons. To delete a term,
- add or delete its superordinates, or compute its relation to another term,
- you must select a term in the right menu. When you do, the buttons corre-
- sponding to these operations will be enabled, and information about the
- chosen term will be displayed. Whenever an existing term must be specified,
- it is done using the term menu. Whenever the object to be a new term
- must be specified, it is done by typing the object into the narrow window."
- :allow-returns t))
-
- ;;-----------------------------
- ;; Menu for selecting the hnet.
- (hnet-menu
- (ccl:oneof
- ccl:*sequence-dialog-item*
- :dialog-item-size (ccl:make-point 100 168)
- :dialog-item-position (ccl:make-point 9 10)
- :table-vscrollp t
- :table-hscrollp nil
- :visible-dimensions (ccl:make-point 1 6)
- :cell-size (ccl:make-point 100 16)
- :table-sequence (sm:instances 'hnet)
- :sequence-order :vertical
- :dialog-item-action
- #'(lambda ()
- (with-hnet
- (ccl:ask ; term-menu
- (second (ccl:ask ccl:my-dialog (ccl:dialog-items)))
- (ccl:set-table-sequence
- (sort (defined-terms hnet) #'object-lessp)))
- (ccl:ask ; display-window
- (fourth (ccl:ask ccl:my-dialog (ccl:dialog-items)))
- (ccl:set-dialog-item-text
- (format nil "HNET ~S's INFO:~%~S~%UNDEFINED TERMS: ~S"
- hnet (hnet-info (sm:gets 'hnet hnet))
- (undefined-terms hnet))))
- ;; Enable applicable buttons, disable rest.
- (ccl:ask ; add-term
- (fifth (ccl:ask ccl:my-dialog (ccl:dialog-items)))
- (ccl:dialog-item-enable))
- (ccl:ask ; undefined-terms
- (ninth (ccl:ask ccl:my-dialog (ccl:dialog-items)))
- (ccl:dialog-item-enable))
- (no-term-selected-handler)))))
-
- ;;-----------------------------------
- ;; Menu for selecting existing terms.
- (term-menu
- (ccl:oneof
- ccl:*sequence-dialog-item*
- :dialog-item-size (ccl:make-point 150 168)
- :dialog-item-position (ccl:make-point 427 10)
- :table-vscrollp t
- :table-hscrollp nil
- :visible-dimensions (ccl:make-point 1 6)
- :cell-size (ccl:make-point 150 16)
- :table-sequence nil
- :sequence-order :vertical
- :dialog-item-action
- #'(lambda ()
- (with-hnet
- (with-term
- ;; Display info about the term. But don't search for
- ;; transitive supers and subs unless all terms defined.
- (ccl:ask ; display-window
- (fourth (ccl:ask ccl:my-dialog (ccl:dialog-items)))
- (ccl:set-dialog-item-text
- (format nil
- "~%~S in HNET ~S:~
- ~% Info: ~S~
- ~% Superordinates: ~S~
- ~% Subordinates: ~S~A"
- term hnet
- (term-info term hnet)
- (superordinates term hnet)
- (subordinates term hnet)
- (if (undefined-terms hnet)
- (format nil "~%UNDEFINED TERMS: ~S"
- (undefined-terms hnet))
- " "))))
- ;; Enable buttons
- (ccl:ask ; delete-term
- (sixth (ccl:ask ccl:my-dialog (ccl:dialog-items)))
- (ccl:dialog-item-enable))
- (ccl:ask ; add-super
- (seventh (ccl:ask ccl:my-dialog (ccl:dialog-items)))
- (ccl:dialog-item-enable))
- (ccl:ask ; delete-super
- (eighth (ccl:ask ccl:my-dialog (ccl:dialog-items)))
- (ccl:dialog-item-enable))
- (ccl:ask ; show-supers
- (ninth (ccl:ask ccl:my-dialog (ccl:dialog-items)))
- (ccl:dialog-item-enable))
- (ccl:ask ; show-subs
- (tenth (ccl:ask ccl:my-dialog (ccl:dialog-items)))
- (ccl:dialog-item-enable)))))))
-
- ;;-----------------------------------------
- ;; Buttons left to right across the top ...
-
- (add-term
- (ccl:oneof
- ccl:*button-dialog-item*
- :dialog-item-text "Add Term"
- :dialog-item-position (ccl:make-point 147 18)
- :dialog-item-enabled-p nil
- :dialog-item-action
- #'(lambda ()
- (with-hnet
- (with-given-object
- (if (member object (defined-terms hnet))
- (progn
- (ccl:ed-beep)
- (ccl:ask ; display-window
- (fourth (ccl:ask ccl:my-dialog (ccl:dialog-items)))
- (ccl:set-dialog-item-text
- (format nil "Oops, ~S is already defined!" object))))
- (progn
- (define-term object nil hnet)
- (ccl:ask ; term-menu
- (second (ccl:ask ccl:my-dialog (ccl:dialog-items)))
- (ccl:set-table-sequence
- (sort (defined-terms hnet) #'object-lessp)))
- (no-term-selected-handler))))))))
-
- (delete-term
- (ccl:oneof
- ccl:*button-dialog-item*
- :dialog-item-text "Delete Term"
- :dialog-item-position (ccl:make-point 140 52)
- :dialog-item-enabled-p nil
- :dialog-item-action
- #'(lambda ()
- (with-hnet
- (with-term
- (when (wind:y-or-n-dialogue "Undefine term ~S?" term)
- (undefine-term term hnet)
- (ccl:ask ; term-menu
- (second (ccl:ask ccl:my-dialog (ccl:dialog-items)))
- (ccl:set-table-sequence
- (sort (defined-terms hnet) #'object-lessp)))
- (no-term-selected-handler)))))))
-
- (add-super
- (ccl:oneof
- ccl:*button-dialog-item*
- :dialog-item-text "Add Super"
- :dialog-item-position (ccl:make-point 247 18)
- :dialog-item-enabled-p nil
- :dialog-item-action
- #'(lambda ()
- (with-hnet
- (with-given-object
- (with-term
- (if (eq term object)
- ;; A common error: forgetting to change the entry window.
- (progn
- (ccl:ed-beep)
- (ccl:ask ; display-window
- (fourth (ccl:ask ccl:my-dialog (ccl:dialog-items)))
- (ccl:set-dialog-item-text
- (format nil
- "Sorry, you can't make ~S a superordinate of itself."
- term))))
- (progn
- (add-superordinate term object hnet)
- ;; Display new info about the term.
- (ccl:ask ; display-window
- (fourth (ccl:ask ccl:my-dialog (ccl:dialog-items)))
- (ccl:set-dialog-item-text
- (format nil
- "~S in HNET ~S:~
- ~% Superordinates: ~S~
- ~% Subordinates: ~S"
- term hnet
- (superordinates term hnet)
- (subordinates term hnet))))))))))))
-
- (delete-super
- (ccl:oneof
- ccl:*button-dialog-item*
- :dialog-item-text "Delete Super"
- :dialog-item-position (ccl:make-point 241 52)
- :dialog-item-enabled-p nil
- :dialog-item-action
- #'(lambda ()
- (with-hnet
- (with-given-object
- (with-term
- (if (eq term object)
- ;; A common error: forgetting to change the entry window.
- (progn
- (ccl:ed-beep)
- (ccl:ask ; display-window
- (fourth (ccl:ask ccl:my-dialog (ccl:dialog-items)))
- (ccl:set-dialog-item-text
- (format nil
- "Sorry, you can't delete ~S as its own superordinate."
- term))))
- (progn
- (delete-superordinate term object hnet)
- ;; Display info about the term.
- (ccl:ask ; display-window
- (fourth (ccl:ask ccl:my-dialog (ccl:dialog-items)))
- (ccl:set-dialog-item-text
- (format nil
- "~S in HNET ~S:~
- ~% Superordinates: ~S~
- ~% Subordinates: ~S"
- term hnet
- (superordinates term hnet)
- (subordinates term hnet))))))))))))
-
- (undefined-terms
- (ccl:oneof
- ccl:*button-dialog-item*
- :dialog-item-text "Undefined"
- :dialog-item-position (ccl:make-point 338 18)
- :dialog-item-enabled-p nil
- :dialog-item-action
- #'(lambda ()
- (with-hnet
- (let ((*print-pretty* t))
- (ccl:ask ; display-window
- (fourth (ccl:ask ccl:my-dialog (ccl:dialog-items)))
- (ccl:set-dialog-item-text
- (if (undefined-terms hnet)
- (format nil
- "Terms referenced in ~S but undefined:~%~S"
- hnet
- (undefined-terms hnet))
- (format nil
- "All terms referenced in ~S are defined." hnet)))))))))
-
- (term-relation
- (ccl:oneof
- ccl:*button-dialog-item*
- :dialog-item-text "Relation"
- :dialog-item-position (ccl:make-point 345 52)
- :dialog-item-enabled-p nil
- :dialog-item-action
- #'(lambda ()
- (with-hnet
- (with-term
- (if (undefined-terms hnet)
- (progn
- (ccl:ed-beep)
- (ccl:ask ; display-window
- (fourth (ccl:ask ccl:my-dialog (ccl:dialog-items)))
- (ccl:set-dialog-item-text
- (format nil
- "RELATION cannot be used until all terms referenced are defined.~
- ~%The following are undefined: ~S"
- (undefined-terms hnet)))))
- (let ((term-to-compare
- (wind:menu-dialogue
- (defined-terms hnet)
- "Compare ~S to which other term?" term))
- (*print-pretty* t))
- (ccl:ask ; display-window
- (fourth (ccl:ask ccl:my-dialog (ccl:dialog-items)))
- (ccl:set-dialog-item-text
- (case (subsumption-relation term term-to-compare hnet)
- ((:subordinate)
- (format nil "~S is SUBORDINATE to ~S in HNET ~S"
- term term-to-compare hnet))
- ((:superordinate)
- (format nil "~S is SUPERORDINATE to ~S in HNET ~S"
- term term-to-compare hnet))
- ((:incomparable)
- (format nil "~S and ~S are INCOMPARABLE in HNET ~S"
- term term-to-compare hnet))))))))))))
-
- ;; Create the browser window itself.
- (browser
- (ccl:oneof ccl:*dialog*
- :window-title " Hierarchical Net Browser "
- :window-position (ccl:make-point 25 45)
- :window-size (ccl:make-point 600 315)
- :window-type :tool
- :dialog-items (list
- hnet-menu ; first
- term-menu ; second
- entry-window ; third
- display-window ; fourth
- add-term ; fifth
- delete-term ; sixth
- add-super ; seventh
- delete-super ; eighth
- undefined-terms ; ninth
- term-relation) ; tenth
- :default-button add-term)))
- browser))
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;
- ;;; GRAPHING HNETS
- ;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- (defparameter *HNET-MOUSE-METHODS*
- (append
- (list
- (cons
- "Make this Node the Root"
- (compile
- nil
- '(lambda (gw gv gn)
- (ccl:ask gw
- (let* ((gv-struct (sm:gets 'grapher:graph-view gv))
- (new-gv
- (hnet->graph-view-with-parameters
- (grapher:graph-view-info-image :hnet gv)
- (list (grapher:graph-node-object
- (sm:gets 'grapher:graph-node gn)))
- (grapher:graph-view-style gv-struct)
- (grapher:graph-view-ordering gv-struct)
- (grapher:graph-view-depth-bound gv-struct)
- gv))) ; parent view
- (grapher:set-graph-view new-gv)
- (ccl:set-window-title
- (sm:prints 'grapher:graph-view new-gv
- :style :name :stream nil))
- (ccl:window-select)
- (ccl:view-draw-contents))))))
-
- (cons
- "Backup Once to Parent View"
- (compile
- nil
- '(lambda (gw gv gn)
- (declare (ignore gn))
- (ccl:ask gw
- (let ((parent-view
- (grapher:graph-view-info-image :parent-view gv)))
- (if parent-view
- (if (sm:gets 'grapher:graph-view parent-view)
- (progn
- (grapher:set-graph-view parent-view :layout nil)
- (ccl:set-window-title
- (sm:prints 'grapher:graph-view parent-view
- :style :name :stream nil))
- (ccl:window-select)
- (ccl:view-draw-contents)
- (unless (grapher:windows-using-graph-view gv)
- (ccl:eval-enqueue `(grapher:dispose-graph-view ',gv))))
- (progn (ccl:ed-beep)
- (setf (grapher:graph-view-info-image :parent-view gv) nil)
- (wind:message-dialogue
- "The parent view appears to have been destroyed.")
- ;; The graph-view of gw was set to nil since we
- ;; thought gv was to be replaced ... restore it.
- (grapher:set-graph-view gv :layout nil)
- (ccl:view-draw-contents)))
- (progn (ccl:ed-beep)
- (wind:message-dialogue
- "This graph view has no parent view.")
- (grapher:set-graph-view gv :layout nil)
- (ccl:view-draw-contents))))))))
-
- (cons
- "New Window with this Node as Root"
- (compile
- nil
- '(lambda (gw gv gn)
- (let* ((hnet (grapher:graph-view-info-image :hnet gv))
- (gv-struct (sm:gets 'grapher:graph-view gv))
- (roots
- (list (grapher:graph-node-object (sm:gets 'grapher:graph-node gn))))
- (style (grapher:graph-view-style gv-struct))
- (ordering (grapher:graph-view-ordering gv-struct))
- (depth-bound (grapher:graph-view-depth-bound gv-struct)))
- (multiple-value-setq
- (roots style ordering depth-bound)
- (grapher:graph-view-parameter-dialogue
- hnet roots nil style ordering depth-bound))
- (ccl:oneof
- grapher:*graph-window*
- :graph-view
- (hnet->graph-view-with-parameters
- hnet roots style ordering depth-bound gv))))))
-
- (cons
- "Backup All the Way to Original View"
- (compile
- nil
- '(lambda (gw gv gn)
- (declare (ignore gn))
- (ccl:ask gw
- (let ((garbage-views nil) (original-view nil))
- ;; Search up to find original view; also recording the views
- ;; to be disposed of along the way.
- (do* ((parent-view
- (grapher:graph-view-info-image :parent-view gv)
- (grapher:graph-view-info-image :parent-view current-view))
- (current-view gv))
- ;; Invariant here: parent-view is parent of current-view,
- ;; so when parent-view nil, current-view is the root.
- ((null parent-view) (setq original-view current-view))
- (if (sm:gets 'grapher:graph-view parent-view)
- (progn
- (push current-view garbage-views)
- (setq current-view parent-view))
- (progn
- (ccl:ed-beep)
- (setf (grapher:graph-view-info-image :parent-view current-view) nil)
- (wind:message-dialogue
- "The parent of view ~A appears to have been destroyed."
- current-view)
- (setq parent-view nil)))) ; to exit
- (grapher:set-graph-view original-view :layout nil) ; already laid out
- (ccl:set-window-title
- (sm:prints 'grapher:graph-view original-view :style :name :stream nil))
- (ccl:window-select)
- (ccl:view-draw-contents)
- (dolist (ggv garbage-views)
- (unless (grapher:windows-using-graph-view ggv)
- (ccl:eval-enqueue `(grapher:dispose-graph-view ',ggv)))))))))
-
- (cons
- "Show Term Info"
- (compile
- nil
- '(lambda (gw gv gn)
- (wind:message-dialogue
- "Term Info of ~S in ~S:~% ~S"
- (grapher:graph-node-object (sm:gets 'grapher:graph-node gn))
- (grapher:graph-view-info-image :hnet gv)
- (term-info (grapher:graph-node-object
- (sm:gets 'grapher:graph-node gn))
- (grapher:graph-view-info-image :hnet gv))))))
- )
- ;; Note that SM stores unevaluated expressions producing defaults.
- (eval
- (cdr (assoc 'grapher::mouse-methods
- (sm:slot-defaults 'grapher:graph-view))))))
-
- (defun GRAPH-HNET (hnet &optional
- (roots (hnet-roots hnet))
- (style :horizontal-tree)
- (ordering :as-found)
- (depth-bound 3))
- "graph-hnet <hnet> &optional <roots> <style> <ordering> <depth-bound>
- With user interaction to possibly modify the parameters, graphs the hnet."
- (check-type hnet symbol)
- (check-type style keyword)
- (check-type ordering keyword)
- (check-type depth-bound fixnum)
- (assert (sm:gets 'hnet hnet) (hnet)
- "[HNET:GRAPH-HNET] Unknown hnet ~S" hnet)
-
- ;; Get desired parameters.
- (multiple-value-setq
- (roots style ordering depth-bound)
- (grapher:graph-view-parameter-dialogue
- hnet roots
- (sort (defined-terms hnet) #'object-lessp)
- style ordering depth-bound))
-
- ;; Graph and put up in window. Exist method handles layout, selecting, and drawing.
- (ccl:oneof grapher:*graph-window*
- :graph-view
- (hnet->graph-view-with-parameters
- hnet roots style ordering depth-bound
- nil)))
-
- (defun HNET->GRAPH-VIEW-WITH-PARAMETERS (hnet roots style ordering depth-bound
- &optional parent-view)
- "hnet->graph-view-with-parameters <hnet> <roots> <style> <ordering>
- &optional <parent-view>
- Returns a graph-view of the HNET with the indicated parameters. The optional
- <parent-view>, if given, should be a graph view, presumably one containing as
- a node the root of the current view. This is an 'internal' function with NO
- ARGUMENT CHECKING."
- (declare (optimize speed))
-
- (let ((graph-view-name
- (utils:unique-symbol
- ;; If the graph is from a unique root, use the same name for the view.
- ;; Otherwise use the hnet name.
- (format nil "~A "
- (if (and roots (null (cdr roots))) (first roots) hnet)))))
- (declare (symbol graph-view-name))
- (grapher:create-graph-view
- graph-view-name
- (build-view-below-roots hnet roots depth-bound parent-view)
- depth-bound style ordering
- '("monaco" 9) '("chicago" 12) 10
- ;; Record this in INFO for use of mouse method.
- `((:hnet . ,hnet) (:parent-view . ,parent-view))
- *hnet-mouse-methods*)))
-
- (defun BUILD-VIEW-BELOW-ROOTS (hnet roots depth-bound parent-view
- &aux (terms->graph-nodes nil))
- ;; return actual roots
- (declare (symbol hnet parent-view) (list roots terms->graph-nodes)
- (fixnum depth-bound) (optimize speed))
-
- ;; Search for terms to be in the graph; generate graph nodes for them if needed.
- (do ((frontier roots)
- (new-frontier nil)
- (depth 0 (1+ depth)))
- ((or (null frontier) (> depth depth-bound)))
- (declare (list frontier new-frontier) (fixnum depth))
- (dolist (term frontier)
- (let ((t+gn (assoc term terms->graph-nodes)))
- (declare (cons t+gn))
- ;; Make sure the node exists.
- (unless (and t+gn (sm:gets 'grapher:graph-node (cdr t+gn)))
- (setq t+gn (cons term (gensym "GRAPH-NODE-")))
- (push t+gn terms->graph-nodes)
- (grapher:create-graph-node
- (cdr t+gn)
- (if (assoc :grapher-upcase (term-info term hnet)) ; label
- (object->string term)
- (string-capitalize (object->STRING term)))
- nil ; children set below
- :rect ; box-style set below
- T ; connector
- term)) ; object
-
- ;; Now that it exists, set current children and box type.
- (let ((gn-struct (sm:gets 'grapher:graph-node (cdr t+gn))))
- ;; These will be changed to graph nodes, once they all exist.
- (setf (grapher:graph-node-children gn-struct) (subordinates term hnet))
- ;; Box style reflects whether it is a top level view root or has children.
- (setf (grapher:graph-node-box-style gn-struct)
- (if (subordinates term hnet)
- (if (and (= depth 0) (null parent-view)) :oval :round-rect)
- :rect)))
-
- (setf new-frontier (append new-frontier (subordinates term hnet)))))
- (setf frontier new-frontier)
- (setf new-frontier nil))
-
- ;; Now that all graph nodes defined, replace child names with graph nodes.
- (dolist (t+gn terms->graph-nodes)
- (declare (cons t+gn))
- (setf (grapher:graph-node-children (sm:gets 'grapher:graph-node (cdr t+gn)))
- (mapcar #'(lambda (term) (cdr (assoc term terms->graph-nodes)))
- (grapher:graph-node-children
- (sm:gets 'grapher:graph-node (cdr t+gn))))))
-
- ;; Returned value is mapping of roots to graph nodes.
- (mapcar #'(lambda (term) (cdr (assoc term terms->graph-nodes)))
- roots))
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- (defparameter *HNET-MENU*
- (let* ((line-item
- (ccl:oneof ccl:*menu-item*
- :menu-item-title "-"))
- (browse-item
- (ccl:oneof ccl:*menu-item*
- :menu-item-title "HNET Browser"
- :menu-item-action #'(lambda () (browse-hnet))))
- (graph-item
- (ccl:oneof ccl:*menu-item*
- :menu-item-title "HNET Grapher ..."
- :menu-item-action
- #'(lambda ()
- (graph-hnet
- (wind:menu-dialogue
- (sm:instances 'hnet)
- "Which HNET do you wish to graph?")))))
- (dispose-item
- (ccl:oneof ccl:*menu-item*
- :menu-item-title "Hide This Menu"
- :menu-item-action
- '(ccl:ask *hnet-menu* (ccl:menu-deinstall))))
- (hnet-menu (ccl:oneof ccl:*menu*
- :menu-title "HNET"
- :menu-items (list browse-item
- graph-item
- line-item
- dispose-item))))
- (ccl:ask hnet-menu (ccl:menu-install))
- (ccl:ask line-item (ccl:menu-item-disable))
- ;; Menu-dispose dumped from version 1.3.1?
- (if (and (boundp '*hnet-menu*)
- (typep *hnet-menu* ccl:*menu*))
- (ccl:ask *hnet-menu* (ccl:menu-deinstall)))
- hnet-menu))
-
- (ccl:ask ccl:*tools-menu*
- (ccl:add-menu-items
- (ccl:oneof ccl:*menu-item*
- :menu-item-title "Restore HNET Menu"
- :menu-item-action
- #'(lambda ()
- (ccl:ask *hnet-menu*
- (unless (ccl:menu-installed-p) (ccl:menu-install)))))))
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- (provide :HNET-BROWSER)
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;; EOF
-